#ifndef ROSTERELEMENTS_H
#define ROSTERELEMENTS_H

#include <QHash>

#include "other/gameStructs.h"
#include "yalb_abstracttreemodel.h"
#include "collections/dualcollection.h"

// \TODO: What about Units with "Replace existing model"?

class Unit;
class ColumnHeader;
class Roster;
class UnitCollection;

typedef QHash<QString, quint8> UnitItems_t;
typedef QSet<QString> UnitOptions_t;
typedef CategoryDataHash ItemLimits_t;

class RosterElement : public yALB_AbstractTreeItem {
    friend class Roster;
public:
    enum ElementType {
        Element = 0,
        RosterUnitType
    };

    RosterElement(RosterElement *_parent);
    ~RosterElement();

    virtual QVariant text(int column, const ColumnHeader *header) const;
    virtual QVariant userData(int column) const;
    virtual ElementType type() const;

    RosterElement* child(int index) const;
    RosterElement* parent() const;

    static void setCurrentRoster(Roster *roster);

    QString name() const;
    void setName(const QString& newName);

    QString key() const;


protected:
    static Roster *currentRoster;

    QString _name;
    QString _key;

private:
    void addChild(RosterElement *child);
    void removeChild(RosterElement *child);
};

class RosterUnit : public RosterElement {
public:
    RosterUnit(const QString& _unitKey, RosterElement *parent);
    ~RosterUnit();

    virtual QVariant text(int column, const ColumnHeader *header) const;
    virtual ElementType type() const;

    Unit getBaseUnit() const;

    uint getSize() const;
    void setSize(uint size);

    uint getMaximumSize() const;
    void setMaximumSize(uint size);

    float getCostPerModel() const;
    void setCostPerModel(float cost);

    float getCost() const;
    void amountCost(float cost);

    bool isAllowedItem(const QString &key, bool checkCategory = true) const;
    QStringList getItemsWithAllowedInf() const;
    void addAllowedItems(const QStringList& value);
    void subtractAllowedItems(const QStringList& value);

    UnitItems_t getItemsInUnit() const;
    bool containsItem(const QString& itemKey) const;
    bool addItem(const QString& itemKey, quint8 number = 1);
    bool subtractItem(const QString& itemKey, quint8 number = 1);
    void removeItem(const QString& itemKey);

    UnitOptions_t getActivatedOptions() const;
    bool isOptionActivated(const QString& optionKey) const;
    bool activateOption(const QString& optionKey);
    bool deactivateOption(const QString& optionKey);

    bool isOptionVisible(const QString& key) const;
    void amountOptionVisible(const QString& key, bool visible);

    bool isOptionLocked(const QString& key) const;
    void amountOptionLocked(const QString& key, bool locked);

    QString getCell(const QString& key) const;
    void amountCell(const QString& key, const QString& value, bool forceAppend = false);
    void subtractCell(const QString& key, const QString& value, bool forcedAppend = false);

    ItemLimits_t getItemLimits() const;
    void amountItemLimits(const CategoryDataHash& newValue);
    void subtractItemLimits(const CategoryDataHash& newValue);

    void addLinkedChild(const QString& unitKey, bool replacesModel);
    void removeLinkedChild(const QString& unitKey);

    static void setCurrentItemCollection(const DualCollection<GameItem> *items);
    static void setCurrentUnitCollection(const UnitCollection *units);

private:
    void deleteNonAllowedItems();

    struct InternalData {
        float points;
        int itemCount;
        InternalData() : points(0.0), itemCount(0) { }
    };
    QHash<QString, InternalData> categoryData;

    UnitItems_t itemsInUnit; // Item key (QString) and number
    UnitOptions_t activatedOptions;

    QHash<QString, qint8> optionVisibleStatus; // Visible if greater than 0
    QHash<QString, qint8> optionLockedStatus; // Locked if greater than 0

    QHash<QString, QString> cells;

    QHash<QString, qint8> allowedItems;
    ItemLimits_t itemLimits; // Category key (QString) and item limits

    float cost;
    float costPerModel;
    uint size;
    uint maximumSize;

    bool replacesModel;
    QHash<QString, RosterUnit*> linkedUnits;

    static const DualCollection<GameItem> *_items;
    static const UnitCollection *_units;
};

#endif // ROSTERELEMENTS_H
